---简易动作状态机

---动作执行状态
---@class EActionExcuteState
EActionExcuteState = {
    INIT = 1;
    ENTER = 2;
    EXCUTE = 3;
    EXIT = 4;
}
---@class GOAPFSMState
---@field excuteState EActionExcuteState
GOAPFSMState = class()
---进入动作,子类重写
function GOAPFSMState:Enter() end
---更新动作,子类重写
function GOAPFSMState:Execute() end
---退出动作,子类重写
function GOAPFSMState:Exit() end

---动作状态机，互斥
---@class GOAPFSM
---@field stateDic table<string,GOAPFSMState>
---@field curState ActionFSMState   当前状态
---@field preState ActionFSMState   以前状态
GOAPFSM = class()

function GOAPFSM:ctor()
    self.stateDic = {}
end
---添加状态到状态机
---@param lable string
---@param state ActionFSMState
function GOAPFSM:AddState(lable, state)
    self.stateDic[lable] = state;
end
---执行新状态
---@param lable string
function GOAPFSM:ExcuteNewState(lable)
    if self.stateDic[lable] == nil then
        Debug.LogError("状态机内不包含此状态");
        return;
    end
    self.preState = self.curState;
    self.curState = self.stateDic[lable];
    if self.preState ~= nil then
        self.preState:Exit();
    end
    if self.curState ~= nil then
        self.curState:Enter();
    end
end
---执行状态，每帧执行
function GOAPFSM:FrameFun()
    if self.curState ~= nil and (self.curState.excuteState == EActionExcuteState.ENTER or self.curState.excuteState == EActionExcuteState.EXCUTE)then
        self.curState:Execute();
    end
end
---协同动作状态机，不互斥
---@class GOAPSyneFSM
---@field stateDic table<string,GOAPFSMState>
GOAPSyneFSM = class()

function GOAPSyneFSM:ctor()
    self.stateDic = {}
end
---添加状态到状态机
---@param lable string
---@param state ActionFSMState
function GOAPSyneFSM:AddState(lable, state)
    self.stateDic[lable] = state;
end
---执行新状态
---@param lable string
function GOAPSyneFSM:ExcuteNewState(lable)
    if self.stateDic[lable] == nil then
        Debug.LogError("状态机内不包含此状态")
        return;
    end
    self.stateDic[lable]:Enter();
end
---执行状态，每帧执行
function GOAPSyneFSM:FrameFun()
    for k, v in pairs(self.stateDic) do
        if v.excuteState == EActionExcuteState.ENTER or v.excuteState == EActionExcuteState.EXCUTE then
            v:Execute();
        end
    end
end